﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.ServiceLocation;
using Pap.Core.Utilities;
using Pap.Data;
using Pap.Data.Abstraction.Utils;
using Pap.Services;
using Pap.Services.WorkflowEngine;
using Pap.Web.Utils;
using Utils;

namespace Pap.Web.Modules.Loan.ViewModel
{
    /// <summary>
    /// 
    /// </summary>
    public class CEOListViewModel : IViewModel
    {
        /// <summary>
        /// 
        /// </summary>
        ILoanRepository _LoanRepository;
        /// <summary>
        /// 
        /// </summary>
        IWorkflowService _WorkFlowService;

        /// <summary>
        /// Initializes a new instance of the <see cref="CEOListViewModel"/> class.
        /// </summary>
        /// <param name="LoanRepository">The loan repository.</param>
        /// <param name="WorkFlowService">The work flow service.</param>
        public CEOListViewModel(ILoanRepository LoanRepository, IWorkflowService WorkFlowService)
        {
            this._LoanRepository = LoanRepository;
            this._WorkFlowService = WorkFlowService;
        }

        /// <summary>
        /// Gets the CEO boards.
        /// </summary>
        /// <returns></returns>
        public IEnumerable GetCEOBoards()
        {
            var boards = _LoanRepository.FindBoard(board => this._WorkFlowService.GetInStep(Steps.BoradCEOList).Contains(board.BoardID));

            return (from board in boards
                    select new
                {
                    BoardID = board.BoardID,
                    BoardNumber = board.BoardNumber,
                    BoardDate = board.BoardDate,
                    BoardStatus = this._WorkFlowService.GetStep(_WorkFlowService.GetProcessInstanceIDByEntity(board.BoardID)).DisplayName.ToString(),
                    ExpertName = this._WorkFlowService.GetStep(_WorkFlowService.GetProcessInstanceIDByEntity(board.BoardID)).User.DisplayName,
                    CommitteeName = board.CommitteeObj.CommitteeName
                });
        }

        /// <summary>
        /// Gets the board loans.
        /// </summary>
        /// <param name="BoardID">The board ID.</param>
        /// <returns></returns>
        public IEnumerable GetBoardLoans(Guid BoardID)
        {
            var CEOLoansIDs = this._WorkFlowService.GetInStep(Steps.CEOList);
            var CEOLoans = this._LoanRepository.GetBoardByID(BoardID).BoardLoans.Where(loan => CEOLoansIDs.Contains(loan.LoanID));
            return (from boardLoan in CEOLoans
                    orderby boardLoan.LoanObj.LoanNumber ascending
                    select new
                    {
                        LoanID = boardLoan.LoanID,
                        LoanNumber = boardLoan.LoanObj.LoanNumber,
                        LoanCreatedDate = boardLoan.LoanObj.LoanCreatedDate,
                        CustomerName = boardLoan.LoanObj.CustomerObj.CustomerName,
                        LoanType = boardLoan.LoanObj.LoanTypeObj.Name,
                        BoardLoanAmount = boardLoan.BoardLoanAmount,
                        BoardPaymentPeriod = boardLoan.BoardPaymentPeriod,
                        ReviewerDecision = _WorkFlowService.GetStep(_WorkFlowService.GetProcessInstanceIDByEntity(boardLoan.LoanID)).DisplayName.ToString(),
                        BoardDecision = _WorkFlowService.GetStep(_WorkFlowService.GetProcessInstanceIDByEntity(boardLoan.LoanID)).PreviousStepAction.DisplayName,
                        PreviousNotes = _WorkFlowService.GetStep(_WorkFlowService.GetProcessInstanceIDByEntity(boardLoan.LoanID)).PreviousNotes
                    });
        }

        /// <summary>
        /// Gets the available actions.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<ActionTypes> GetAvailableActions()
        {
            return _WorkFlowService.GetAvailableActionsByStep(Steps.BoradCEOList);
        }


        /// <summary>
        /// Submits the boards.
        /// </summary>
        /// <param name="BoardsIDs">The boards I ds.</param>
        /// <param name="BoardsDecisions">The boards decisions.</param>
        /// <param name="NotesList">The notes list.</param>
        public void SubmitBoards(List<Guid> BoardsIDs, List<Guid> BoardsDecisions, List<string> NotesList)
        {
            using (IUnitOfWork transaction = ServiceLocator.Current.GetInstance<IUnitOfWork>())
            {
                bool haveValidLoans = false;
                var CEOLoans = this._WorkFlowService.GetInStep(Steps.CEOList);
                Dictionary<string, int> dicActions = Enums.ToNameKeyPaires(typeof(ActionTypes));
                for (int i = 0; i < BoardsIDs.Count; i++)
                {
                    IBoard board = _LoanRepository.GetBoardByID(BoardsIDs[i]);
                    foreach (var loanItem in board.BoardLoans)
                    {
                        if (CEOLoans.Contains(loanItem.LoanID))
                        {
                            Guid processInstID = _WorkFlowService.GetProcessInstanceIDByEntity(loanItem.LoanID);
                            if (BoardsDecisions[i].Equals(Enums.ToString(ActionTypes.Accept).ToGuid()))
                            {
                                var step = _WorkFlowService.GetStep(processInstID);
                                _WorkFlowService.Move(step.ActionType, processInstID, RegistryInfo.UserID, "", step.CompletionDate);
                                Guid decisionID = Enums.ToString(step.ActionType).ToGuid();
                                if (decisionID.Equals(Enums.ToString(ActionTypes.Accept).ToGuid()))
                                    haveValidLoans = true;
                                //if() check to delete a loan from board

                            }
                            else
                            {
                                //_WorkFlowService.Move(ActionTypes.Return, processInstID, RegistryInfo.UserID, "");
                                _WorkFlowService.SendBack(processInstID);
                            }
                        }
                    }
                    _WorkFlowService.Move((ActionTypes)dicActions[BoardsDecisions[i].ToString()], _WorkFlowService.GetProcessInstanceIDByEntity(BoardsIDs[i]), RegistryInfo.UserID, NotesList[i], null);

                    if (!haveValidLoans)
                    {
                        transaction.Commit();
                        _WorkFlowService.Move(ActionTypes.Submit, _WorkFlowService.GetProcessInstanceIDByEntity(BoardsIDs[i]), RegistryInfo.UserID, NotesList[i], null);
                    }
                }
                transaction.Commit();
            }
        }
    }
}
